using Shielded.Gossip;
using System;
using System.Collections.Generic;
using System.Net;
using ConsoleApp1;
using System.Threading;
using Shielded;

namespace GossipCore
{
    public class HazeCluster : IDisposable
    {
        public ITransport Transport { get; }
        public GossipBackend Backend { get; }

        private bool _started = false;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id">当前节点ID</param>
        /// <param name="peers">ID:IPEndPoint</param>
        public HazeCluster(string id, IDictionary<string, IPEndPoint> peers)
        {
            Serializer.Use(new BrokerSerializer());
            Transport = new NettyTransport(id, peers);
            Backend = new GossipBackend(Transport, new GossipConfiguration()
            {
                GossipInterval = 250,
                AntiEntropyIdleTimeout = 2000,
            });
            
            var backendHandler = Transport.MessageHandler;
            Transport.MessageHandler = msg =>
            {
                OnMessage(id, msg);
                return backendHandler(msg);
            };
        }

        private void OnMessage(string id, object msg)
        {
            if (msg is GossipStart or GossipEnd) return;
            Console.WriteLine($"收到消息：id={id},msg={msg}");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <param name="peers">id,(host:port)</param>
        public HazeCluster(string id, IDictionary<string, string> peers)
            : this(id, ArgsParser.ConvertToIPEndPoints(peers)) { }

        public void Start(int waitTime=1000)
        {
            if (_started) return;
            Transport.Start();
            // 启动后立即全量同步
            var spreadRumorsMethod = Backend.GetType().GetMethod("SpreadRumors", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
            spreadRumorsMethod?.Invoke(Backend, null);
            _started = true;
            Thread.Sleep(waitTime); // 默认2秒延迟，确保节点重启后有足够时间同步
        }

        public Topic<T> GetTopic<T>(string name)
        {
            return new Topic<T>(Backend, name);
        }


        public void Dispose()
        {
            Backend?.Dispose();
            Transport?.Dispose();
        }
    }

    
}